import sys
import math
from PyQt5.QtWidgets import QApplication, QWidget, QFileDialog
from PyQt5.QtGui import QImage, QPainter, QPainterPath, QLinearGradient, QColor, QPalette
from PyQt5.QtCore import Qt, QTimer, QRectF, QPoint

class WaterReflectionWidget(QWidget):
    def __init__(self, image_path):
        super().__init__()
        
        # 加载并初始化图片
        self.original_image = QImage(image_path)
        if self.original_image.isNull():
            raise ValueError("无法加载图片文件")
        
        # 窗口设置
        self.setWindowTitle("PyQt5 水波倒影效果")
        self.setFixedSize(self.original_image.width(), 
                         self.original_image.height() * 1.8)  # 留出倒影空间
        
        # 水波参数
        self.wave_phase = 0.0
        self.wave_amplitude = 100    # 波浪振幅
        self.wave_speed = 0.12     # 波浪移动速度
        self.wave_frequency = 0.15 # 波浪密度
        
        # 倒影参数
        self.reflection_height_ratio = 0.6  # 倒影占原图高度比例
        self.reflection_opacity = 0.85      # 倒影初始透明度
        
        # 生成倒影图像
        self.generate_reflection_image()
        
        # 动画定时器
        self.animation_timer = QTimer(self)
        self.animation_timer.timeout.connect(self.update_wave)
        self.animation_timer.start(30)  # 约33fps

    def generate_reflection_image(self):
        """生成倒影图像并预处理"""
        # 垂直翻转
        self.reflection_image = self.original_image.mirrored(False, True)
        
        # 添加透明度渐变
        gradient = QLinearGradient(0, 0, 0, self.reflection_image.height())
        gradient.setColorAt(0, QColor(255, 255, 255, int(255 * self.reflection_opacity)))
        gradient.setColorAt(1, Qt.transparent)
        
        painter = QPainter(self.reflection_image)
        painter.setCompositionMode(QPainter.CompositionMode_DestinationIn)
        painter.fillRect(self.reflection_image.rect(), gradient)
        painter.end()

    def update_wave(self):
        """更新波浪相位"""
        self.wave_phase += self.wave_speed
        self.update()

    def paintEvent(self, event):
        painter = QPainter(self)
        painter.setRenderHint(QPainter.Antialiasing)
        
        # 绘制原始图片
        painter.drawImage(0, 0, self.original_image)
        
        # 绘制倒影（带水波效果）
        self.draw_water_reflection(painter)

    def draw_water_reflection(self, painter):
        """绘制水波倒影"""
        # 计算倒影区域
        img_height = self.original_image.height()
        reflection_rect = QRectF(
            0, img_height,
            self.original_image.width(),
            img_height * self.reflection_height_ratio
        )
        
        # 创建波浪路径
        wave_path = self.generate_wave_path(reflection_rect)
        
        # 设置裁剪区域
        painter.save()
        painter.setClipPath(wave_path)
        
        # 绘制倒影图像
        painter.drawImage(reflection_rect, self.reflection_image)
        painter.restore()
        
        # 添加水波高光效果
        self.draw_water_highlight(painter, reflection_rect)

    def generate_wave_path(self, rect):
        """生成波浪形路径"""
        path = QPainterPath()
        path.moveTo(rect.left() - 10, rect.top())
        
        # 使用复合波浪公式
        for x in range(int(rect.left() - 10), int(rect.right() + 10)):
            # 基础波浪
            y1 = math.sin(self.wave_frequency * x + self.wave_phase)
            
            # 次级波浪
            y2 = 0.5 * math.sin(1.8 * self.wave_frequency * x + 1.2 * self.wave_phase)
            
            # 组合波形
            y = self.wave_amplitude * (y1 + y2)
            
            path.lineTo(x, rect.top() + y)
        
        path.lineTo(rect.right() + 10, rect.bottom())
        path.lineTo(rect.left() - 10, rect.bottom())
        path.closeSubpath()
        
        return path

    def draw_water_highlight(self, painter, rect):
        """绘制水波高光效果"""
        highlight = QLinearGradient(rect.topLeft(), rect.bottomLeft())
        highlight.setColorAt(0, QColor(255, 255, 255, 80))
        highlight.setColorAt(0.7, Qt.transparent)
        
        painter.setPen(Qt.NoPen)
        painter.setBrush(highlight)
        painter.drawRect(rect)

    def mousePressEvent(self, event):
        """点击窗口选择新图片"""
        if event.button() == Qt.LeftButton:
            self.change_image()

    def change_image(self):
        """更换图片文件"""
        path, _ = QFileDialog.getOpenFileName(
            self, "选择图片", "", 
            "Images (*.png *.jpg *.bmp)"
        )
        if path:
            self.original_image = QImage(path)
            self.generate_reflection_image()
            self.update()

if __name__ == "__main__":
    app = QApplication(sys.argv)
    
    # 使用示例图片或通过命令行参数指定
    image_path = "../img/beauty02.png" if len(sys.argv) < 2 else sys.argv[1]
    
    try:
        window = WaterReflectionWidget(image_path)
        window.show()
    except ValueError as e:
        print(e)
        sys.exit(1)
    
    sys.exit(app.exec_())

#*******************************
#使用说明：
# 在__init__方法中调整这些参数：
# self.wave_amplitude = 10    # 波浪高度
# self.wave_speed = 0.12      # 波浪移动速度
# self.wave_frequency = 0.15 # 波浪密度（数值越大波浪越密）
# self.reflection_height_ratio = 0.6  # 倒影高度比例
# self.reflection_opacity = 0.85       # 倒影透明度